package rok3.projekt.zespver3.utils;

import static rok3.projekt.zespver3.network.packet.__PrimitiveSignal__.ready__;
import static rok3.projekt.zespver3.network.packet.__PrimitiveSignal__.start__;

import java.io.IOException;

import rok3.projekt.zespver3.client.MyGame;
import rok3.projekt.zespver3.client.Settings;
import rok3.projekt.zespver3.client.screens.InGameScreen;
import rok3.projekt.zespver3.client.screens.InGameStage;
import rok3.projekt.zespver3.client.screens.RoomScreen;
import rok3.projekt.zespver3.network.Network;
import rok3.projekt.zespver3.network.packet.CharacterState__;
import rok3.projekt.zespver3.network.packet.Event__;
import rok3.projekt.zespver3.network.packet.__AllChanges;
import rok3.projekt.zespver3.network.packet.__PrimitiveSignal__;
import rok3.projekt.zespver3.network.packet.__StartGameInfo;
import rok3.projekt.zespver3.network.packet.__YourId;

import com.badlogic.gdx.Screen;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.DelayedRemovalArray;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;

public class GameClientUpdater {

	private final Client client;
	private MyGame game;
	private boolean needfix;
	public short my_id;
	
	public Array<CharacterState__> states = new Array<CharacterState__> (true,32);
	public final int LIST_MAX_SIZE = 128;

	public GameClientUpdater(final MyGame game) {
		this.game = game;
		client = new Client();
		Network.register(client);
		client.addListener(new Listener() {
			@Override
			public void connected(Connection connection) {
				System.out.println("Client> connected");
				DelayedRemovalArray<Object> a;
			}

			@Override
			public void disconnected(Connection connection) {
				System.out.println("Client> disconnected");
				client.stop();
				System.exit(-1);
			}

			@Override
			public void received(Connection connection, Object object) {
				/*
				 * Primitive signals
				 */
				if ( object instanceof __PrimitiveSignal__) {
					__PrimitiveSignal__ signal = (__PrimitiveSignal__) object;
					switch (signal ) {
						/*
						 * Primitive signals : start request denied
						 */
						case __start_not_ok: {
							Screen s= game.getScreen();
							if ( s instanceof RoomScreen ) {
								((RoomScreen)s).waitForStart = false;
							}
							break;
						}
						default : {
							System.out.println("ClientUpdater#recived: unknown primitive signal");
						}
					}
				}
				
				/*
				 * Characters states for updating
				 */
				if ( object instanceof __AllChanges ){
					__AllChanges __changes = (__AllChanges) object;
					Screen s= game.getScreen();
					if ( s instanceof InGameScreen ) {
						InGameStage stage = ((InGameScreen)s).getStage();
						if (stage != null){
							stage.applyUpdatesFromServer(__changes);
						}
					}
				}
				
				/*
				 * Information about client's id, received right after the client has been connected to the server
				 */
				if ( object instanceof __YourId ) {
					__YourId your_id = (__YourId) object;
					GameClientUpdater.this.my_id = your_id.id;
					System.out.printf("My id : %d\n", your_id.id);
				}
				
				/*
				 * Information about the game, need for creating stage in InGameScreen : number of players, ids, 
				 */
				if ( object instanceof __StartGameInfo ) {
					__StartGameInfo sgi = (__StartGameInfo) object;
					Screen s= game.getScreen();
					if ( s instanceof RoomScreen ) {
						((RoomScreen)s).setStartGameInfo(sgi);
					}
				}
				
			}
		});
		new Thread(client).start();
	}
	
	public void tryConnecting () throws IOException{
		client.connect(Settings._time_out, Settings._host_address[Settings._host_selection],Settings._port_tcp, Settings._port_udp);

	}
	
	public boolean isConnected() {
		return client.isConnected();
	}
	public Client getKryonetClient() {
		return client;
	}

	public void sendCharacterState(CharacterState__ state) {
		if ( states.size <= LIST_MAX_SIZE) states.add(state);
		client.sendUDP(state);
	}

	public void applyStates() {
		if (!needfix)
			return;
	}
	
	public void sendReadySignal() {

		System.out.println("before trycon : " + client.isConnected() );
		client.sendTCP(ready__);
	}
	public void sendStartSignal() {
		client.sendTCP(start__);
	}

	public void sendEvents(Event__[] event) {
		if( event.length != 0 ) client.sendUDP(event);
	}

}
